#pragma once 
#include <iostream>
#include <queue>
#include <vector>
#include <functional>
#include <pthread.h>
#include "log.hpp"
#include "lockguard.hpp"
#include "thread.hpp"

static const int defaultnum = 5;

class threaddata
{
public:
    threaddata(const std::string& name):threadname(name)
    {}
    ~threaddata(){}
    std::string threadname;
};

template<class T>
class threadpool
{
private:
    threadpool(int num = defaultnum):_thread_num(num)
    {
        pthread_mutex_init(&_mutex, NULL);
        pthread_cond_init(&_cond, NULL);

        for(int i = 0; i < _thread_num; i++)
        {
            std::string threadname = "thread-";
            threadname += std::to_string(i + 1); 

            threaddata td(threadname);
            // Thread<ThreadData> t(threadname,
            //                      std::bind(&threadpool<T>::ThreadRun, this, std::placeholders::_1), td);
            // _threads.push_back(t);
            _thread.emplace_back(threadname,
                                  std::bind(&threadpool<T>::ThreadRun, this,
                                            std::placeholders::_1),
                                  td);
            lg.logmessage(Info, "%s is created...\n", threadname.c_str());//日志
        }
    }

    threadpool(const threadpool<T>& tp) = delete;//禁止拷贝复制或赋值复制
    const threadpool &operator=(const threadpool<T>) = delete;
public:
    //有关线程安全的    
    static threadpool<T>* getinstance()//单例模式，只允许有一个实例
    {
        lockguard Lg(&sig_lock);
        if(instance == NULL){
            lg.logmessage(Info, "创建单例成功...\n");
            instance = new threadpool<T>(); 
        }
        return instance;
    }
    bool start()
    {
        for(auto &thread: _thread)
        {
            thread.start();
            lg.logmessage(Info, "%s is running ...\n", thread.name().c_str());
        }
        return true;
    }
    void threadwait(const threaddata& data){
        lg.logmessage(Debug, "no task, %s is sleeping ...\n", data.threadname.c_str());
        pthread_cond_wait(&_cond, &_mutex);
    }
     void ThreadWakeup()
    {
        pthread_cond_signal(&_cond);
    }
    void checkSelf()
    {
        // 1. _task_num > _task_num_high_water && _thread_num < _thread_num_high_water
        // 创建更多的线程，并且更新_thread_num

        // 2. _task_num == _task_num_low_water && _thread_num >= _thread_num_high_water
        // 把自己退出了，并且更新_thread_num
    }
    void ThreadRun(const threaddata& td)//    _thread : _func   ###########################
    {
        while(true)
        {
            checkSelf();
            //取任务
            T t;//task
            {//作用域外LG自动回收
                lockguard LG(&_mutex);
                while(_q.empty())
                {
                    threadwait(td);
                    lg.logmessage(Debug, "thread %s is wakeup\n", td.threadname.c_str());
                }
                t = _q.front();
                _q.pop();
                
            }
            // 处理任务
            t();
            lg.logmessage(Debug, "%s handler task %s done, result is : %s\n",
                          td.threadname, t.PrintTask().c_str(), t.PrintResult().c_str());
        }
    }
    void push(T& in)
    {
        lg.logmessage(Debug, "other thread push a task, task is : %s \n", in.PrintTask().c_str());
        lockguard LG(&_mutex);
        _q.push(in);
        ThreadWakeup();
    }
    ~threadpool()
    {
        pthread_mutex_destroy(&_mutex);
        pthread_cond_destroy(&_cond);
    }

    // for debug
    void wait()
    {
        for (auto &thread : _thread)
        {
            thread.join();
        }
    }
private:
    std::queue<T> _q;
    std::vector<thread<threaddata>> _thread;
    int _thread_num;//线程数量
    pthread_mutex_t _mutex;
    pthread_cond_t _cond;


    static threadpool<T> *instance;
    static pthread_mutex_t sig_lock;
};

template <class T>
threadpool<T> *threadpool<T>::instance = nullptr;
template <class T>
pthread_mutex_t threadpool<T>::sig_lock = PTHREAD_MUTEX_INITIALIZER;